#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266HTTPUpdateServer.h>
#include <Wire.h>
#include "OLED.h"


int InPutLast = 1;
bool isStateCahnge = true;
ESP8266WiFiMulti WiFiMulti;

ESP8266WebServer server(80);
ESP8266HTTPUpdateServer httpUpdater;

// Declare OLED display
// display(SDA, SCL);
// SDA and SCL are the GPIO pins of ESP8266 that are connected to respective pins of display.
OLED display(2, 14);

const int led = LED_BUILTIN;
const int InPin = 12;

const char* host = "esp";

  const String postForms = "<html>\
  <head>\
    <meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes\" />\
    <title>ESP8266 Web Control</title>\
    <style>\
      body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }\
      intput{width:100%;}\
    </style>\
    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes\" />\
  </head>\
  <body>\
    <h4>POST plain text to /setgpio/</h4><br>\
    <form method=\"post\" enctype=\"application/x-www-form-urlencoded\" action=\"/setgpio/\">\
      <input type=\"text\" name=\"pin\" value=\"12\"><br>\
      <input type=\"text\" name=\"model\" value=\"input\"><br>\
      <input type=\"text\" name=\"val\" value=\"1\"><br>\
      <input type=\"submit\" value=\"Submit\">\
    </form>\
    <h4>POST form data to /getgpio/</h4><br>\
    <form method=\"post\" enctype=\"application/x-www-form-urlencoded\" action=\"/getgpio/\">\
      <input type=\"text\" name=\"pin\" value=\"12\"><br>\
      <input type=\"text\" name=\"val\" value=\"1\"><br>\
      <input type=\"submit\" value=\"Submit\">\
    </form>\
  </body>\
</html>";

char * strAdd(char *str1, char *str2) {
  char *str = (char *) malloc(strlen(str1) + strlen(str2));
  sprintf(str, "%s%s", str1, str2);
  return str;
}

void handleRoot() {
  digitalWrite(led, 1);
  server.send(200, "text/html", postForms);
  digitalWrite(led, 0);
  display.print("handleRoot");
}

void handleSetgpio() {
  if (server.method() != HTTP_POST) {
    digitalWrite(led, 1);
    server.send(405, "text/plain", "Method Not Allowed");
    digitalWrite(led, 0);
  } else {
    digitalWrite(led, 1);
    server.send(200, "text/plain", "POST body was:\n" + server.arg("plain") + server.arg("pin") + server.arg("model") + server.arg("val"));
    digitalWrite(led, 0);
  }
  display.print("Setgpio");
  digitalWrite(led, 1);
}

void handleGetgpio() {
  if (server.method() != HTTP_POST) {
    digitalWrite(led, 1);
    server.send(405, "text/plain", "Method Not Allowed");
    digitalWrite(led, 0);
  } else {
    digitalWrite(led, 1);
    String message = "POST form was:\n";
    for (uint8_t i = 0; i < server.args(); i++) {
      message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
    }
    server.send(200, "text/plain", message);
    digitalWrite(led, 0);
  }
  display.print("Getgpio");
}

void handleNotFound() {
  digitalWrite(led, 1);
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
  digitalWrite(led, 0);
  //display.print("File Not Found\n\n");
}


void handleHttpData() {
  digitalWrite(led, 1);
  HTTPClient http;

  Serial.print("[HTTP] begin...\n");
  // configure traged server and url
  //获取URL
  String url = server.arg("url");
  http.begin(url); //HTTP

  Serial.print("[HTTP] GET:\n");
  Serial.println(url);
  // start connection and send HTTP header
  int httpCode = http.GET();

  // httpCode will be negative on error
  if (httpCode > 0) {
    // HTTP header has been send and Server response header has been handled
    Serial.printf("[HTTP] GET... code: %d\n", httpCode);

    // file found at server
    if (httpCode == HTTP_CODE_OK) {
      String payload = http.getString();
      Serial.println(payload);
      server.send(httpCode, "text/plain", &payload[0]);
    } else {
      server.send(httpCode, "text/plain", "error");
    }

  } else {
    Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
  }

  http.end();
  digitalWrite(led, 0);
}


void notify(char *msg) {
  digitalWrite(led, 1);

  Serial.println(msg);
  display.print(msg, 1);
  //return;
  Serial.print("[HTTP] begin...\n");
  // configure traged server and url
  char *url = strAdd("http://jpf.vipgz2.idcfengye.com/notify/monitor.php?id=", msg);
  Serial.println(url);
  HTTPClient http;
  http.begin(url); //HTTP
  Serial.print("[HTTP] GET:\n");
  // start connection and send HTTP header
  int httpCode = http.GET();

  // httpCode will be negative on error
  if (httpCode > 0) {
    // HTTP header has been send and Server response header has been handled
    Serial.printf("[HTTP] GET... code: %d\n", httpCode);

    // file found at server
    if (httpCode == HTTP_CODE_OK) {
      String payload = http.getString();
      Serial.println(payload);
      server.send(httpCode, "text/plain", &payload[0]);
    } else {
      server.send(httpCode, "text/plain", "error");
    }

  } else {
    Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
  }

  http.end();
  digitalWrite(led, 0);
}

void initServer() {

  server.on("/", handleRoot);

  server.on("/setgpio/", handleSetgpio);

  server.on("/getgpio/", handleGetgpio );
  server.on("/httpData/", handleHttpData);

  server.onNotFound(handleNotFound);
  display.print("server start");
}


void setup(void) {
  //OLED
  // Initialize display
  display.begin();
  pinMode(led, OUTPUT);
  pinMode(GPIO_ID_PIN(InPin), INPUT);
  digitalWrite(led, 0);
  Serial.begin(115200);

  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP("jj", "JPF@jj5201314");
  WiFiMulti.addAP("nmo", "e6gps1656");
  //WiFi.begin(STASSID, STAPSK);
  display.print("wifi Connecting...");
  // Wait for connection
  //while (WiFi.status() != WL_CONNECTED) {
  while (WiFiMulti.run() != WL_CONNECTED) {
    Serial.print("*");
    digitalWrite(led, 1);
    delay(500);
    digitalWrite(led, 0);
    delay(500);
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(WiFi.SSID().c_str());
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  if (MDNS.begin(host)) {
    Serial.println("MDNS responder started");
  }
  isStateCahnge = true;
}


void loop(void) {
  // wait for data to be available
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print("*");
    digitalWrite(led, 1);
    delay(500);
    digitalWrite(led, 0);
    delay(500);
    isStateCahnge = true;
  }
  if (isStateCahnge) {
    display.clear();
    isStateCahnge = false;
    String ip = WiFi.localIP().toString();
    String ssid = WiFi.SSID();
    char *wifiinfo = strAdd(&ssid[0], &ip[0]);
    display.print(wifiinfo, 2);
    notify(wifiinfo);
    initServer();
   httpUpdater.setup(&server);
    MDNS.addService("http", "tcp", 80);
    server.begin();
  MDNS.update();
    Serial.println("HTTP server started");
   Serial.printf("HTTPUpdateServer ready! Open http://%s.local/update in your browser\n", host);
  }
  int flag = digitalRead(InPin);
  //软操作消抖
  int count = 0;
  while (flag != InPutLast) {
    flag = digitalRead(InPin);
    count++;
    delay(10);
    if (count > 10) {
      InPutLast = flag;
      Serial.print("State Changed:");
      InPutLast = flag;
      if (InPutLast > 0) {
        Serial.println("on");
        notify("on");
      } else {
        notify("off");
        Serial.println("off");
      }
      break;
    }
  }
  server.handleClient();
}
